/*
 * MyThreadClass.h
 *
 *  Last edited: 18.08.2014
 *  Author: David Noack
 */

#ifndef MYTHREADCLASS_H_
#define MYTHREADCLASS_H_

#include <pthread.h>
#include <stdlib.h>


/**
\class MyThreadClass
\brief Implements Thread-handling for two threads within an object.

MyThreadClass defines two methods thread_work() and thread_listen(prthread_t) which have to be implemented by
classes who inherit from MyThreadClass. The class got two internal variables for two threads. The class is intended to work like this:
- thread_work() have to do all the connection setup and executing commands if something is received from a client, the function will run in thread _worker.
- thread_lisen() got a endless loop, where it waits for receiving data from a client, the cuntion will run in thread _listener.

- If thread_listen receives some data (within the thread _listener) it will signal the thread _worker.
- The thread _worker will check the signal within the function thread_worker() and do some computation or whatever.
- As long as the worker is busy, the listener can receive commands, but they will not be executed.
- After finishing a computation, the worker will get ready again and can handler further commands from the listener.
*/
class MyThreadClass
{
public:
	
	/**Constructor*/
   MyThreadClass()
   {
	   _worker = 0;
	   _listener = 0;
   }
   /**Destructor*/
   virtual ~MyThreadClass() {/* empty */}

   /**
   Starts the worker thread, which start executing the thread_work() function.
   \return True if the thread was successfully started, false if there was an error starting the thread.*/
   int StartWorkerThread()
   {
      return (pthread_create(&_worker, NULL, thread_workEntryFunc, this) == 0);
   }

   /**
   Starts the listen thread, which start executing the thread_listen() function.
   \return True if the thread was successfully started, false if there was an error starting the thread.*/
   int StartListenerThread(pthread_t parent_th)
   {
	   return (pthread_create(&_listener, NULL, thread_listenerEntryFunc, this) == 0);
   }


   /** Will not return until the internal worker thread has exited. */
   void WaitForWorkerThreadToExit()
   {
      (void) pthread_join(_worker, NULL);
   }

   /** Will not return until the internal listener thread has exited. */
   void WaitForListenerThreadToExit()
   {
	   (void) pthread_join(_listener, NULL);
   }

protected:

	/** This method has to be responsible for the connection setup and execution tasks like prngd computation.*/
   virtual void thread_work() = 0;
   /**This method has to be responsible for listening to incomming data and signaling the worker.*/
   virtual void thread_listen(pthread_t)= 0;

private:
	/** Creates a new worker thread and starts executing thread_work within it.*/
   static void * thread_workEntryFunc(void * This) {((MyThreadClass *)This)->thread_work(); return NULL;}
   /** Creates a new listener thread and starts executin thread_listen within it.*/
   static void * thread_listenerEntryFunc(void * This) {((MyThreadClass *)This)->thread_listen(((MyThreadClass *)This)->_worker); return NULL;}

   /** Id of the internal worker thread.*/
   pthread_t _worker;
   /** ID of the internal listener thread.*/
   pthread_t _listener;
};



#endif /* MYTHREADCLASS_H_ */
